package hu.monitor.remoting.server;

import hu.monitor.remoting.InterceptorChain;
import hu.monitor.remoting.InvocationContext;
import hu.monitor.remoting.client.MarshalledInvocation;
import hu.monitor.remoting.transport.RequestProcessor;

import java.lang.reflect.Method;

public class InterceptorChainRequestProcessor implements RequestProcessor {
	private final InterceptorChain chain;

	public InterceptorChainRequestProcessor(final InterceptorChain chain) {
		this.chain = chain;
	}

	@Override
	public Object processRequest(final Object object) throws Throwable {
		final MarshalledInvocation invocation = (MarshalledInvocation)object;
		final InvocationContext context = this.createInvocationContext(invocation);
		return this.chain.processInvocation(context);
	}

	private InvocationContext createInvocationContext(final MarshalledInvocation invocation) throws Exception {
		final Class<?> remoteInterface = Class.forName(invocation.getInterfaceName());
		final Method method = this.findMethod(invocation, remoteInterface);
		final Object[] args = invocation.getArguments();
		final InvocationContext context = new InvocationContext(remoteInterface, method, args);
		return context;
	}

	private Method findMethod(final MarshalledInvocation invocation, final Class<?> remoteInterface) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
		final String methodName = invocation.getMethodName();
		final String[] typeNames = invocation.getParameterTypeNames();
		final Class<?>[] types = new Class<?>[typeNames.length];
		for (int i = 0; i < types.length; i++) {
			types[i] = Class.forName(typeNames[i]);
		}

		return remoteInterface.getMethod(methodName, types);
	}

}
